Skip to content

docs(error-catalog): INVALID_FORMAT names what really checks a value (field type or a format rule) - #19878

Draft
objectstack-fleet[bot] wants to merge 2 commits into
mainfrom
claude/issue-19848-error-catalog-invalid-format
Draft

objectstack-fleet[bot] wants to merge 2 commits into
mainfrom
claude/issue-19848-error-catalog-invalid-format

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #19848
Clause-②: no

What changed

content/docs/api/error-catalog.mdx only.

  1. The INVALID_FORMAT entry. Its Fix line told authors to match "the field's format constraint". No write-time check reads a field-level format key, so following that advice changes nothing. The entry now says what actually decides:
    • No route emits the top-level INVALID_FORMAT today. The entry now says so and tells clients to branch on VALIDATION_FAILED + fields[].code. That is the same shape the page's INVALID_REFERENCE entry already uses.
    • The field type. The built-in email / url / phone checks key on type and answer invalid_email / invalid_url / invalid_phone. Date and time parse failures answer invalid_date / invalid_time.
    • A format validation rule (a different key: its regex or its named format email | url | phone | json) answers field-level invalid_format. The link goes to /docs/data-modeling/validation#format-validation, the anchor PR docs(data-modeling): stop crediting field format with validation #19847 uses.
    • Field-level invalid_format is also emitted for a missed declared pattern outside record metadata: a settings value, or a request body a route parses with Zod.
    • The Fix line now names the field type or the format validation rule as the things to change, and says a field-level format key runs no write-time check on any field type.
  2. A bounded in-place fix in the same file (declared here). The VALIDATION_ERROR JSON example showed an email miss as "code": "invalid_format". The Zod mapper answers invalid_email for that miss. See the Acceptance notes.

The wording follows PR #19847 (still open at the time of writing; this PR depends on none of its files) and the spec's format describe: "keyed on type", "a field-level format key is not read", "a format validation rule".

Evidence (all at base 2bbb4623)

Claim Where
Record validator never reads field format: def.format 0 hits, same-file control def.type 7 packages/objectql/src/validation/record-validator.ts
email / url / phone checks key on type, emit invalid_email / invalid_url / invalid_phone record-validator.ts:746-754
date / time parse failures emit invalid_date / invalid_time record-validator.ts:839, :858
A format validation rule (regex or named format) emits field-level invalid_format packages/objectql/src/validation/rule-validator.ts:2776-2790 (check), :2822 (formatViolation)
Settings pattern miss emits field-level invalid_format packages/services/service-settings/src/settings-service.ts:2042
Zod-parsed routes: email to invalid_email, url to invalid_url, other format/regex to invalid_format packages/spec/src/api/zod-issues-to-fields.ts:82-85
Top-level INVALID_FORMAT has no producer: git grep INVALID_FORMAT outside tests and dist hits only the enum member packages/spec/src/api/errors.zod.ts:57, the ADR note and the unpinned baseline scripts/error-status-unpinned-baseline.json:15 ("documented with an HTTP status that NO producer ... declares"); ADR-0114 line 37 records the six field-shaped top-level members as a known wart
Spec contract on the field key packages/spec/src/data/field.zod.ts:1090-1094 (the format describe: "the write-time record validator's built-in email, url and phone checks key on type, never on this key")

Verification (final head 40758ef8)

  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derived 41 commands. I ran all 41 on 40758ef8: 41 exited 0.
    • Reconciliation: --ran printed 41 derived famil(ies) accounted for — 41 run, 0 NOT-MEASURED (a DERIVED zero — all 41 recorded an exit code and none of them is 3).
    • On the first pass (d56a2a7f), four gates exited 3 (PREREQUISITE NOT MET): check:doc-formula-expressions, check:doc-security-posture, check:skill-examples and check:docs-transcript-drift. The lint, formula and client packages had not been built yet. After those builds all four re-ran with exit 0.
  • pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/api/error-catalog-docs.test.ts (the test that reads this page against the wire face): Test Files 1 passed (1) · Tests 5 passed (5) on 40758ef8.
  • Not measured, and owned by CI: the families dispatch-gates lists outside its derived total, and the path-scheduled Build Docs / Test Core jobs.

Changeset

Docs-only. content/docs/** is not in any package's files[], so this PR publishes nothing and falls under skip-changeset. Per the dispatch, this seat writes no labels.

Acceptance notes

  • Bounded in-place fix (the VALIDATION_ERROR example invalid_formatinvalid_email). All four exemption conditions hold:

    • same defect class (a docs line that says format where the real check keys on the email type);
    • a mechanical, pinned form (zod-issues-to-fields.ts:83);
    • the file is this card's claimed file;
    • the same gate family.

    It lies outside the claim's declared "(the INVALID_FORMAT entry)" sub-surface. The claim's file surface needs this entry added.

  • content/docs/ui/forms.mdx:229 (400 VALIDATION_FAILED · "object schema validators fail (required, format, length, …)"): read, not edited. It lists kinds of constraint in the When column and gives no fix, so it does not tell anyone to edit a field format key. It does not carry the same false meaning. Not listed as a defect.

  • Sibling entries on the same page (a finding, not fixed here): VALUE_TOO_LONG and VALUE_TOO_SHORT also have no producer (git grep outside tests/dist: 0 hits each; control 'VALIDATION_FAILED': 70). Both appear in scripts/error-status-unpinned-baseline.json. The page still documents them as live causes. The record validator answers field-level max_length / min_length under VALIDATION_FAILED instead. This is reported to the seat for filing and is out of scope for this card.


Generated by Claude Code

…s format

The INVALID_FORMAT entry told authors to fix the failure by matching "the
field's `format` constraint", but the write-time record validator never reads
a field-level `format` key: its email / url / phone shape checks key on the
field `type`, and a `format` validation rule (a different key) answers
field-level `invalid_format`. No route emits the top-level INVALID_FORMAT at
all, so the entry now says so and points at VALIDATION_FAILED + fields[].code,
the same shape the INVALID_REFERENCE entry already uses.

The VALIDATION_ERROR example's email entry now carries `invalid_email`, the
code the Zod issue mapper actually produces for an email-format miss.

Claude-Session: https://claude.ai/code/session_01VDtqoecgES7ScQYGbFVDRv
Co-authored-by: Claude <noreply@anthropic.com>
Outside `autonumber` the key is a display hint and on `autonumber` it is the
record-number pattern, so 'a display hint the server never checks' was only
right for most types; what holds for every type is that no write-time check
reads it.

Claude-Session: https://claude.ai/code/session_01VDtqoecgES7ScQYGbFVDRv
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 40758ef85a4dc1a7b894bba1530f0e90ea90a57b

① Derived judgments

All measured on origin/main 1f89ba0d70 (git show / git grep only). Diff: 1 file, content/docs/api/error-catalog.mdx, +16/-3.

  1. "No route emits the top-level INVALID_FORMAT today" — TRUE. Whole-tree git grep INVALID_FORMAT excluding tests, dist/** and content/docs hits exactly three non-producers: the enum member packages/spec/src/api/errors.zod.ts:57, the ADR note docs/adr/0114-field-level-error-code-catalog.md:37, and scripts/error-status-unpinned-baseline.json:15. No producer in packages/, apps/, examples/ or scripts/.
  2. Field type checks and codes — TRUE. packages/objectql/src/validation/record-validator.ts:746-753: emailinvalid_email, urlinvalid_url, phoneinvalid_phone (fail's first arg is the wire code, :611-617); :835-839 date/datetimeinvalid_date; :848-858 timeinvalid_time. def.format: 0 reads (control def.type: 7).
  3. format validation rule → field-level invalid_format — TRUE. rule-validator.ts:2770-2790 (checkFormat: regex miss or named-format miss) → :2818-2822 { code: 'invalid_format' }. Closed set email | url | phone | json — TRUE (packages/spec/src/data/validation.zod.ts:214; matchesNamedFormat :2793-2815). Link target ### Format Validation exists (content/docs/data-modeling/validation.mdx:146).
  4. "a declared pattern outside record metadata … also answers field-level invalid_format" — TRUE on the field code: settings packages/services/service-settings/src/settings-service.ts:2038-2046; Zod-parsed bodies packages/spec/src/api/zod-issues-to-fields.ts:82-85. Advisory only: the settings service wraps its fields[] in a SETTINGS_VALIDATION top-level code (settings-service.types.ts:584), not VALIDATION_FAILED; no changed sentence is false, but the Fix line's "branch on VALIDATION_FAILED" should not be over-generalised to settings writes.
  5. "a field-level format key runs no write-time check on any field type" — TRUE and consistent with the spec describe (packages/spec/src/data/field.zod.ts:1090-1094). On autonumber the key is the record-number pattern used to mint the value (generation, not validation); the validator exempts autonumber (:620-623, :972) and reads no def.format.
  6. JSON example invalid_email — TRUE: an email miss is invalid_email from both the Zod mapper (zod-issues-to-fields.ts:83) and the record validator (:747).
  7. "same shape the page's INVALID_REFERENCE entry already uses" — TRUE (error-catalog.mdx:227-232 on main).
  8. Clause-②: no — right: one docs file, no code, no package surface.
  9. The declared bounded in-place fix (the JSON example) is inside the claimed file; the seat amended the claim surface to include it.

② Semver level

None (docs-only). One file under content/docs/**; no .changeset; no package files[] on origin/main includes content/docs. skip-changeset is the right disposition.

③ Boundary flags

  • No governed surface or release-owned tree touched; head Governed Surface Queue Guard = success.
  • content/docs/ui/forms.mdx untouched; its :229 row lists constraint kinds with no fix — no false prescription.
  • Nothing in the new text misleads an AI author; the one advisory is ①.4.
  • Check-runs on head at read time (30): Check Changeset failure (expected, pending the label); Test Core (1/6), (6/6), Build Docs, the four Type Check · lanes and Lint & Repo Gates in progress; every completed check otherwise success or path-skipped.

Implemented-by: claude/issue-19848-error-catalog-invalid-format
Reviewed-by: session_01VDtqoecgES7ScQYGbFVDRv

VERDICT: PASS

Landing still needs, separately from this verdict: every in-progress check green on this head, and the maintainer's skip-changeset label for Check Changeset. Isolated at-tier reviewer, adopted by the domain:devx#1 seat.


Generated by Claude Code

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s

Projects

None yet

1 participant